
import mqtt from 'mqtt';
import moment from 'moment';
import db from './mysqlHelper.js';
import { mqttConfig } from './configuration.js';

//从数据库加载报警配置值
let alarmConfig = await db.query(`select * from alarm_set`);


let askArray = [];

let mq_client = mqtt.connect(`mqtt://${mqttConfig.host}:${mqttConfig.port}`, {
    username: mqttConfig.username, password: mqttConfig.password, clientId: moment().unix(),
    keepalive: 60, clean: true
});
mq_client.on('connect', async () => {
    console.log(`与MQTT服务器的连接成功`);
    console.log(`订阅主题 /cae/oms/IMEI/status`);
    // mq_client.subscribe(`/cae/oms/869020066193648/status`);
    mq_client.subscribe(`/cae/oms/status`);
    // setTimeout(()=>{
    //     openFan('869020066193648');
    // },1000)

})

function boolToNumber(bool) {
    if (bool) {
        return 1;
    }
    else {
        return 0;
    }
}

mq_client.on('message', async (topic, message) => {

    // let sn = topic.split('/')[3]
    // console.log(`接收到MQTT服务器的消息`, topic, sn);s
    let strMessage = message.toString();
    console.log(`接收到MQTT服务器的消息`, topic, strMessage);
    let rec_obj = null;
    try {
        rec_obj = JSON.parse(strMessage);
    } catch (error) {
        console.log('数据解析失败', error.message, strMessage);
        return;
    }
    // rec_obj.sn = sn;
    // if (rec_obj.sn == null) {
    //     console.log("接收到的数据没有SN", topic, rec_obj);
    //     return;
    // }
    // console.log('接收到的数据', rec_obj);
    if (rec_obj.cmd) {
        console.log('接收到命令', rec_obj.cmd,JSON.stringify(rec_obj));
        //   let sn = rec_obj.imei;
        let cmd = rec_obj.cmd;
        if (cmd == 'hb') {
            console.log('收到心跳', rec_obj);
            let real = await db.findOne('device_real', { sn: rec_obj.imei });
            //   console.log('查询设备是否有实时数据',real,realData.sn)
            if (real) {
                if (real.rssi != rec_obj.rssi || real.is_online == false) {
                    await db.update('device_real', { rssi: rec_obj.rssi, is_online: true, last_time: moment().format('YYYY-MM-DD HH:mm:ss') },
                     { sn: rec_obj.imei });
                    await db.update('device', { status: 1 }, { sn: rec_obj.imei })
                }
                else {
                    console.log('rssi相同，不更新');
                }
            }
            else {
                let realData = {
                    sn: rec_obj.imei,
                    is_online: 1,
                    last_time: moment().format('YYYY-MM-DD HH:mm:ss')
                }
                await db.create('device_real', realData);
                await db.update('device', { status: 1 }, { sn: rec_obj.imei })
            }

            //   let res =await openFan(sn);
            //   console.log('开启风机',res);
        }
        else if (cmd == 'offline') {
            await db.update('device_real', { is_online: false }, { sn: rec_obj.imei });
            await db.update('device', { status: 0 }, { sn: rec_obj.imei })
        }

        else {
            if (rec_obj.id) {
                askArray.push(rec_obj.id);
                console.log('askArray', askArray);
            }

            if (cmd == 'report' || cmd == 'queryAsk') {
                let realData = {
                    sn: rec_obj.imei,
                    is_online: 1,
                    temp: rec_obj.temp,
                    humidity: rec_obj.humidity,
                    yynd: rec_obj.oil,
                    klw: rec_obj.pm,
                    ch4: rec_obj.ch4,
                    fjzt: boolToNumber(rec_obj.fs),
                    jhqzt: boolToNumber(rec_obj.ps),
                    fjdl: rec_obj.fc,
                    jhqdl: rec_obj.pc,
                    fjqkzt: boolToNumber(rec_obj.fcs),
                    jhyqkzt: boolToNumber(rec_obj.pcs),
                    last_time: moment().format('YYYY-MM-DD HH:mm:ss')
                }
                if(rec_obj.db){
                    realData.db = rec_obj.db;
                }
                //console.log('实时数据',realData);
                let real = await db.findOne('device_real', { sn: realData.sn });
                //   console.log('查询设备是否有实时数据',real,realData.sn)

                 realData.alarm_status = 0;
                if (real.alarm_status) {
                    realData.alarm_status = real.alarm_status;
                }
                //检查报警值
                for (let i = 0; i < alarmConfig.length; i++) {
                    let alarm = alarmConfig[i];
                    if (realData[alarm.code] > alarm.alarm_value) {

                        if (getAlarmValue(realData.alarm_status, alarm.alarm_bit) == 0) {
                            realData.alarm_status = setAlarmValue(alarm_status, alarm_bit);
                            //  生成报警记录
                            let alarmData = {
                                sn: rec_obj.imei,
                                alarm_time: moment().format('YYYY-MM-DD HH:mm:ss'),
                                alarm_name: alarm.name,
                                alarm_value: alarm.code,
                                alarm_value: realData[alarm.code],
                                status:1 //报警状态  开始报警
                            }
                            await db.create('alarm', alarmData);
                        }

                    }else if (realData[alarm.code] < alarm.clear_value) {
                        if (getAlarmValue(realData.alarm_status, alarm.alarm_bit) == 1) {
                            realData.alarm_status = clearAlarmValue(alarm_status, alarm_bit);
                            //  生成报警记录
                            let alarmData = {
                                sn: rec_obj.imei,
                                alarm_time: moment().format('YYYY-MM-DD HH:mm:ss'),
                                alarm_name: alarm.name,
                                alarm_value: alarm.code,
                                alarm_value: realData[alarm.code],
                                status:0 // 报警解除 停止报警

                            }
                        }
                    }
                }


                if (real) {
                    console.log('更新实时数据', JSON.stringify(realData));
                    await db.update('device_real', realData, { sn: rec_obj.imei });
                }
                else {
                    console.log('创建实时数据', JSON.stringify(realData));
                    await db.create('device_real', realData);
                }
                realData.report_time = moment().format('YYYY-MM-DD HH:mm:ss');
                delete realData.last_time;


                await db.create('device_record', realData);
            }
        }


    }
})

function setAlarmValue(value, bit) {
    bit--;
    return value | (1 << bit);
}
//按位清除报警值
function clearAlarmValue(value, bit) {
    bit--;
    return value & ~(1 << bit);
}
//按位获取报警值
function getAlarmValue(value, bit) {
    bit--;
    return value >> bit & 1;
}



mq_client.on('error', (err) => {
    console.log(`与MQTT服务器的连接出错`, err.message);
})
mq_client.on('close', () => {
    console.log(`与MQTT服务器的连接关闭`);
});
//

async function sleep(time) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve();
        }, time)
    })
}

async function openFan(sn) {
    const topic = `/cae/oms/${sn}/comm`;
    const data = {
        cmd: 'startfan',
        id: moment().unix()

    }
    console.log('发送消息', topic, JSON.stringify(data));
    mq_client.publish(topic, JSON.stringify(data));
    let timeOut = moment().add(5, 's');
    while (moment().isBefore(timeOut) && askArray.includes(data.id) == false) {

        await new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve();
            }, 1000)
        })
    }
    if (askArray.includes(data.id)) {
        askArray = askArray.filter(item => item != data.id);
        return { code: 1, message: 'success' };
    }
    else {
        return { code: 0, message: 'timeout' };
    }

}
async function closeFan(sn) {

    const topic = `/cae/oms/${sn}/comm`;
    const data = {
        cmd: 'stopfan',
        id: moment().unix()

    }
    console.log('发送消息', topic, JSON.stringify(data));
    mq_client.publish(topic, JSON.stringify(data));
    let timeOut = moment().add(5, 's');
    while (moment().isBefore(timeOut) && askArray.includes(data.id) == false) {

        await new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve();
            }, 1000)
        })
    }
    if (askArray.includes(data.id)) {
        askArray = askArray.filter(item => item != data.id);
        return { code: 1, message: 'success' };
    }
    else {
        return { code: 0, message: 'timeout' };
    }
}
async function startpurification(sn) {

    const topic = `/cae/oms/${sn}/comm`;
    const data = {
        cmd: 'startpurification',
        id: moment().unix()

    }
    console.log('发送消息', topic, JSON.stringify(data));
    mq_client.publish(topic, JSON.stringify(data));
    let timeOut = moment().add(5, 's');
    while (moment().isBefore(timeOut) && askArray.includes(data.id) == false) {

        await new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve();
            }, 1000)
        })
    }
    if (askArray.includes(data.id)) {
        askArray = askArray.filter(item => item != data.id);
        return { code: 1, message: 'success' };
    }
    else {
        return { code: 0, message: 'timeout' };
    }
}
async function stoppurification(sn) {

    const topic = `/cae/oms/${sn}/comm`;
    const data = {
        cmd: 'stoppurification',
        id: moment().unix()

    }
    console.log('发送消息', topic, JSON.stringify(data));
    mq_client.publish(topic, JSON.stringify(data));
    let timeOut = moment().add(5, 's');
    while (moment().isBefore(timeOut) && askArray.includes(data.id) == false) {

        await new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve();
            }, 1000)
        })
    }
    if (askArray.includes(data.id)) {
        askArray = askArray.filter(item => item != data.id);
        return { code: 1, message: 'success' };
    }
    else {
        return { code: 0, message: 'timeout' };
    }
}
async function restart(sn) {

    const topic = `/cae/oms/${sn}/comm`;
    const data = {
        cmd: 'restart',
        id: moment().unix()

    }
    console.log('发送消息', topic, JSON.stringify(data));
    mq_client.publish(topic, JSON.stringify(data));
    let timeOut = moment().add(5, 's');
    while (moment().isBefore(timeOut) && askArray.includes(data.id) == false) {

        await new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve();
            }, 1000)
        })
    }
    if (askArray.includes(data.id)) {
        askArray = askArray.filter(item => item != data.id);
        return { code: 1, message: 'success' };
    }
    else {
        return { code: 0, message: 'timeout' };
    }
}
async function setinterval(sn, interval) {

    const topic = `/cae/oms/${sn}/comm`;
    const data = {
        cmd: 'setinterval',
        id: moment().unix(),
        interval

    }
    console.log('发送消息', topic, JSON.stringify(data));
    mq_client.publish(topic, JSON.stringify(data));
    let timeOut = moment().add(5, 's');
    while (moment().isBefore(timeOut) && askArray.includes(data.id) == false) {

        await new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve();
            }, 1000)
        })
    }
    if (askArray.includes(data.id)) {
        askArray = askArray.filter(item => item != data.id);
        return { code: 1, message: 'success' };
    }
    else {
        return { code: 0, message: 'timeout' };
    }

}


async function queryStatus(sn) {
    const topic = `/cae/oms/${sn}/comm`;
    const data = {
        cmd: 'query',
        id: moment().unix()
    }
    console.log('发送消息', topic, JSON.stringify(data));
    mq_client.publish(topic, JSON.stringify(data));
    return { code: 1, message: 'success' };


    // let timeOut=moment().add(5,'s');

    // while(moment().isBefore(timeOut) && askArray.includes(data.id)==false){

    //     await new Promise((resolve,reject)=>{
    //         setTimeout(()=>{
    //             resolve();
    //         },1000)
    //     })
    // }
    // if(askArray.includes(data.id)){
    //     askArray = askArray.filter(item=>item!=data.id);
    //     return {code:1,message:'success'};
    // }
    // else{
    //     return {code:0,message:'timeout'};
    // }

}




export default { openFan, closeFan, setinterval, restart, stoppurification, startpurification, queryStatus }